package com.jt.www.biz.order_pc.controller;

import com.alibaba.fastjson.JSON;
import com.github.pagehelper.PageInfo;
import com.google.common.collect.Maps;
import com.jt.www.biz.order_pc.service.EndorseService;
import com.jt.www.domain.qo.EndorsQueryParam;
import com.jt.www.domain.qo.EndorsementsEduQueryVO;
import com.jt.www.domain.vo.EduPolicyVO;
import com.jt.www.enums.endorse.EndorTypeEnum;
import com.jt.www.enums.endorse.EndorsementsStatusEnum;
import com.jt.www.enums.endorse.EndorsementsTypeEnum;
import com.jt.www.enums.endorse.PolicyTypeEnum;
import com.jt.www.enums.extend.ExcelDownFileEnum;
import com.jt.www.exception.ParamException;
import com.jt.www.model.param.endorse.*;
import com.jt.www.model.reps.GenericDataResponse;
import com.jt.www.model.reps.GenericListResponse;
import com.jt.www.model.reps.GenericResponse;
import com.jt.www.model.vo.endorse.CheckNumVO;
import com.jt.www.model.vo.endorse.EndorseResponseVo;
import com.jt.www.util.CommonUtils;
import com.jt.www.util.JsonUtil;
import com.jt.www.util.excel.ExcelUtils;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import net.sf.jxls.transformer.XLSTransformer;
import org.apache.commons.lang.StringUtils;
import org.apache.poi.ss.usermodel.Workbook;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.io.ClassPathResource;
import org.springframework.core.io.Resource;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import springfox.documentation.annotations.ApiIgnore;

import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.validation.Valid;
import java.io.InputStream;
import java.util.List;
import java.util.Map;

@Api(value = "批单相关接口", description = "批单相关接口")
@RestController
@RequestMapping(value = "/pro")
public class EndorseController {

    public static final Logger log = LoggerFactory.getLogger(EndorseController.class);
    @Autowired
    private EndorseService endorseService;

    @ApiOperation(value = "批单上传并校验人员", httpMethod = "POST")
    @PostMapping(value = "/v1/endorse/upload", produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
    public ResponseEntity checkPerson(EndorseParam param,
                                      @ApiParam(value = "批单excel", required = true) @RequestParam MultipartFile excelFile) {
        int endorType = param.getEndorType();
        if (EndorTypeEnum.getByCode(endorType) == null) {
            throw new ParamException("不正确的批单类型");
        }
        int policyType = param.getPolicyType();
        if (PolicyTypeEnum.getByCode(policyType) == null) {
            throw new ParamException("不正确的险种类型");
        }
        EndorseResponseVo responseVo = endorseService.uploadEndorse(param, excelFile);
        if (responseVo.getFileId() != null) {
            return GenericDataResponse.okWithData(responseVo);
        } else {
            StringBuilder stringBuilder = new StringBuilder();
            responseVo.getErrorMsgList().forEach(stringBuilder::append);
            return GenericResponse.ng(String.valueOf(stringBuilder));
        }
    }

    @ApiIgnore
    @ApiOperation(value = "替换清单上传并校验人员", httpMethod = "POST")
    @PostMapping(value = "/v1/endorse/upload-replace", produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
    public ResponseEntity checkReplacePerson(@ApiParam(value = "投保单号", required = true) @RequestParam String insuranceId,
                                             @ApiParam(value = "险种类型：0-实责险（企业），1-实责险（学校），2-校责险（学校），" +
                                                     "4-云南教职工，10-云南校责，13-云南综合，16-山东校责,18-山东临沂,17-校园食品安全责任保险", required = true) @RequestParam Integer policyType,
                                             @ApiParam(value = "替换清单excel", required = true) @RequestParam MultipartFile replaceExcelFile,
                                             @ApiParam(value = "被替换清单文件id", required = true) @RequestParam String originFileId) {
        if (PolicyTypeEnum.getByCode(policyType) == null) {
            throw new ParamException("不正确的险种类型");
        }
        EndorseResponseVo responseVo = endorseService.checkReplaceEndorse(insuranceId, policyType, replaceExcelFile, originFileId);
        if (responseVo.getFileId() != null && responseVo.getFileId() != null) {
            return GenericDataResponse.okWithData(responseVo);
        } else {
            StringBuilder stringBuilder = new StringBuilder();
            responseVo.getErrorMsgList().forEach(stringBuilder::append);
            return GenericResponse.ng(String.valueOf(stringBuilder));
        }
    }


    @ApiOperation(value = "替换清单上传并校验人员", httpMethod = "POST")
    @PostMapping(value = "/v2/endorse/upload-replace", produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
    public ResponseEntity checkReplacePersonV2(@ApiParam(value = "用户编码", required = true) @RequestParam String userCode,
                                               @ApiParam(value = "投保单号", required = true) @RequestParam String insuranceId,
                                               @ApiParam(value = "险种类型：0-实责险（企业），1-实责险（学校），2-校责险（学校），4-云南教职工，10-云南校责，13-云南综合，16-山东校责，18-山东临沂,17-校园食品安全责任保险", required = true) @RequestParam Integer policyType,
                                               @ApiParam(value = "替换清单excel", required = true) @RequestParam MultipartFile replaceExcelFile,
                                               @ApiParam(value = "被替换清单文件id", required = true) @RequestParam String originFileId) {
        if (PolicyTypeEnum.getByCode(policyType) == null) {
            throw new ParamException("不正确的险种类型");
        }
        EndorseResponseVo responseVo = endorseService.checkReplaceEndorseV2(userCode, insuranceId, policyType, replaceExcelFile, originFileId);
        if (responseVo.getFileId() != null && responseVo.getFileId() != null) {
            return GenericDataResponse.okWithData(responseVo);
        } else {
            StringBuilder stringBuilder = new StringBuilder();
            responseVo.getErrorMsgList().forEach(stringBuilder::append);
            return GenericResponse.ng(String.valueOf(stringBuilder));
        }
    }

    @ApiOperation(value = "被替换清单上传并校验人员", httpMethod = "POST")
    @PostMapping(value = "/v2/endorse/upload-origin", produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
    public ResponseEntity checkOriginPersonv2(@ApiParam(value = "用户编码", required = true) @RequestParam String userCode,
                                              @ApiParam(value = "投保单号", required = true) @RequestParam String insuranceId,
                                              @ApiParam(value = "险种类型：0-实责险（企业），1-实责险（学校），2-校责险（学校），3-实责险（学校）批单" +
                                                      "4-云南教职工，10-云南校责，13-云南综合，16-山东校责,18-山东临沂,17-校园食品安全责任保险", required = true) @RequestParam Integer policyType,
                                              @ApiParam(value = "被替换清单excel", required = true) @RequestParam MultipartFile originExcelFile) {
        if (PolicyTypeEnum.getByCode(policyType) == null) {
            throw new ParamException("不正确的险种类型");
        }
        EndorseResponseVo responseVo = endorseService.checkOriginEndorseV2(userCode, insuranceId, policyType, originExcelFile);
        if (responseVo.getFileId() != null && responseVo.getFileId() != null) {
            return GenericDataResponse.okWithData(responseVo);
        } else {
            StringBuilder stringBuilder = new StringBuilder();
            responseVo.getErrorMsgList().forEach(stringBuilder::append);
            return GenericResponse.ng(String.valueOf(stringBuilder));
        }
    }

    @ApiIgnore
    @ApiOperation(value = "被替换清单上传并校验人员", httpMethod = "POST")
    @PostMapping(value = "/v1/endorse/upload-origin", produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
    public ResponseEntity checkOriginPerson(@ApiParam(value = "投保单号", required = true) @RequestParam String insuranceId,
                                            @ApiParam(value = "险种类型：0-实责险（企业），1-实责险（学校），2-校责险（学校），" +
                                                    "4-云南教职工，10-云南校责，13-云南综合，16-山东校责,18-山东临沂,17-校园食品安全责任保险", required = true) @RequestParam Integer policyType,
                                            @ApiParam(value = "被替换清单excel", required = true) @RequestParam MultipartFile originExcelFile) {
        if (PolicyTypeEnum.getByCode(policyType) == null) {
            throw new ParamException("不正确的险种类型");
        }
        EndorseResponseVo responseVo = endorseService.checkOriginEndorse(insuranceId, policyType, originExcelFile);
        if (responseVo.getFileId() != null && responseVo.getFileId() != null) {
            return GenericDataResponse.okWithData(responseVo);
        } else {
            StringBuilder stringBuilder = new StringBuilder();
            responseVo.getErrorMsgList().forEach(stringBuilder::append);
            return GenericResponse.ng(String.valueOf(stringBuilder));
        }
    }

    @ApiOperation(value = "批单-立即出单，保存批单数据", httpMethod = "POST")
    @PostMapping(value = "/v1/endorse/endorse", produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
    public ResponseEntity saveEndorse(@RequestBody @Valid SaveEndorseParam param) {
        int endorType = param.getEndorType();
        if (EndorTypeEnum.getByCode(endorType) == null) {
            return GenericResponse.ng("不正确的批单类型");
        }
        if (endorType == EndorTypeEnum.REPLACE.getCode()) {
            if (StringUtils.isBlank(param.getFileId()) || StringUtils.isBlank(param.getOriginFileId())) {
                return GenericResponse.ng("文件id不能为空");
            }
        }
        if (endorType != EndorTypeEnum.SURRENDER.getCode() && endorType != EndorTypeEnum.ALL_ADD_INSURANT.getCode()
                && endorType != EndorTypeEnum.ALL_DEL_INSURANT.getCode()) {
            if (StringUtils.isBlank(param.getFileId())) {
                return GenericResponse.ng("文件id不能为空");
            }
        }
        int i = endorseService.saveEndorse(param);
        if (i > 0) {
            return GenericResponse.ok();
        } else {
            return GenericResponse.ng("保存不成功");
        }
    }

    @ApiOperation(value = "批单-删除后，删除人员清单预入库记录", httpMethod = "GET")
    @GetMapping(value = "/v1/endorse/delete", produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
    public ResponseEntity delete(@ApiParam(value = "用户编码", required = true) @RequestParam String applyId) {
        if (StringUtils.isBlank(applyId)) {
            return GenericResponse.ng("批单-定单号不能为空！");
        }
        int n = endorseService.deleteByApplyId(applyId);
        if (n > 0) {
            return GenericResponse.ok();
        }
        return GenericResponse.ng("删除不成功，请联系管理人员!");
    }

    @ApiOperation(value = "投保单-立即出单，保存投保单数据", httpMethod = "POST")
    @PostMapping(value = "/v1/endorse/insurance", produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
    public ResponseEntity saveInsurance(@RequestBody SaveInsParam param) {
        if (CommonUtils.isEmpty(param.getAppCode())) {
            throw new ParamException("投保单号不能为空");
        } else {
            for (String s : param.getAppCode()) {
                if (StringUtils.isBlank(s)) {
                    throw new ParamException("投保单号不能为空");
                }
            }
        }
        if (StringUtils.isBlank(param.getUsercode())) {
            throw new ParamException("用户编号不能为空");
        }

        boolean policyTypeFlag;
        int policyType = param.getPolicyType();
        if (PolicyTypeEnum.getByCode(policyType) == null) {
            throw new ParamException("不能识别的险种类型");
        } else policyTypeFlag = policyType == PolicyTypeEnum.TRAINEE_ENT.getCode()
                || policyType == PolicyTypeEnum.TRAINEE_SCH.getCode()
                || policyType == PolicyTypeEnum.STUDENT_SCH.getCode();
        int i = endorseService.saveInsurance(param.getAppCode(), param.getUsercode(), policyTypeFlag, true);
        if (i > 0) {
            return GenericResponse.ok();
        } else {
            return GenericResponse.ng("保存不成功");
        }
    }

    @ApiOperation(value = "批单-线下出单，保存批单数据", httpMethod = "POST")
    @PostMapping(value = "/v1/endorse/endorse-offline", produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
    public ResponseEntity saveEndorseParam(@RequestBody @Valid SaveEndorseParam param) {
        int endorType = param.getEndorType();
        if (EndorTypeEnum.getByCode(endorType) == null) {
            throw new ParamException("不正确的批单类型");
        }
        int i = endorseService.saveEndorseParam(param);
        if (i > 0) {
            return GenericResponse.ok();
        } else {
            return GenericResponse.ng("保存不成功");
        }
    }

    @ApiOperation(value = "投保单-线下出单，保存投保单数据", httpMethod = "POST")
    @PostMapping(value = "/v1/endorse/insurance-offline", produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
    public ResponseEntity saveInsuranceParam(@RequestBody SaveInsParam param) {
        String findCode = "saveInsuranceParam_" + System.currentTimeMillis();

        log.info("{} saveInsuranceParam 入参->{}", findCode, JsonUtil.object2Json(param));

        if (CommonUtils.isEmpty(param.getAppCode())) {
            log.error("{} 投保单号不能为空", findCode);
            throw new ParamException("投保单号不能为空");
        } else {
            for (String s : param.getAppCode()) {
                if (StringUtils.isBlank(s)) {
                    log.error("{} 投保单号不能为空!", findCode);
                    throw new ParamException("投保单号不能为空");
                }
            }
        }
        if (StringUtils.isBlank(param.getUsercode())) {
            log.error("{} 用户编号不能为空", findCode);
            throw new ParamException("用户编号不能为空");
        }
        int i = endorseService.saveInsuranceParam(param.getAppCode(), param.getUsercode(), findCode);

        log.info("{} saveInsuranceParam i->{}", findCode, i);
        if (i > 0) {
            log.info("{} saveInsuranceParam 清单记录保存", findCode);
            return GenericResponse.ok();
        } else {
            log.info("{} saveInsuranceParam 清单记录保存不成功，请联系管理员！", findCode);
            return GenericResponse.ng("清单记录保存不成功，请联系管理员！");
        }
    }

    @ApiOperation(value = "投保单扫描记录生效", httpMethod = "PUT")
    @PutMapping(value = "/v1/endorse/ins-param-eff", produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
    public ResponseEntity insParamEff(@RequestBody InsEffParam insEffParam) {
        if (StringUtils.isBlank(insEffParam.getAppCode())) {
            throw new ParamException("投保单号不能为空");
        }
        int i = endorseService.effectiveInsParam(insEffParam.getAppCode());
        if (i > 0) {
            return GenericResponse.ok();
        } else {
            return GenericResponse.ng("修改不成功");
        }
    }

    @ApiOperation(value = "批单单扫描记录生效", httpMethod = "PUT")
    @PutMapping(value = "/v1/endorse/endor-param-eff", produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
    public ResponseEntity endorParamEff(@RequestBody EndorEffParam endorOrderCode) {
        if (StringUtils.isBlank(endorOrderCode.getEndorOrderCode())) {
            throw new ParamException("批单订单号不能为空");
        }
        int i = endorseService.effectiveEndParam(endorOrderCode.getEndorOrderCode());
        if (i > 0) {
            return GenericResponse.ok();
        } else {
            return GenericResponse.ng("修改不成功");
        }
    }

    @ApiOperation(value = "替换和被替换具体人员信息", httpMethod = "GET")
    @GetMapping(value = "/v1/endorse/replace-detail", produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
    public ResponseEntity replaceDetail(@ApiParam(value = "替换文件id", required = true) @RequestParam("replaceFileId") String replaceFileId,
                                        @ApiParam(value = "被替换文件id", required = true) @RequestParam("originFileId") String originFileId,
                                        @ApiParam(value = "险种类型：0-实责险（企业），1-实责险（学校），2-校责险（学校），" +
                                                "4-云南教职工，10-云南校责，13-云南综合，16-山东校责", required = true) @RequestParam("policyType") Integer policyType) {
        Map map = endorseService.replaceDetail(replaceFileId, originFileId, policyType);
        return GenericDataResponse.okWithData(map);
    }

    @ApiOperation(value = "出单后补录清单", httpMethod = "POST")
    @PostMapping(value = "/v1/endorse/addFiles", produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
    public ResponseEntity addFiles(@RequestBody AddEndorseFileParam param) {
        if (StringUtils.isBlank(param.getAppCode())) {
            throw new ParamException("投保单号不能为空");
        }
        if (StringUtils.isBlank(param.getUsercode())) {
            throw new ParamException("用户编号不能为空");
        }
        if (CommonUtils.isEmpty(param.getFileIds())) {
            throw new ParamException("文件id不能为空");
        }

        int i = endorseService.addFiles(param.getAppCode(), param.getUsercode(), param.getFileIds());
        if (i > 0) {
            return GenericResponse.ok();
        } else {
            return GenericResponse.ng("保存不成功");
        }
    }


    @ApiOperation(value = "计算批单需要付款/退款的人数", notes = "计算批单需要付款/退款的人数", httpMethod = "POST")
    @PostMapping(value = "/v1/endorse/checkNum", produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
    public ResponseEntity checkPayPersonNum(@RequestBody @Valid List<CheckNumVO> listVo) {

//        if(StringUtils.isEmpty(jsonStr)){
//            return GenericDataResponse.errorWithMsg("参数不能为空");
//        }

        if (listVo == null || listVo.size() == 0) {
            return GenericDataResponse.errorWithMsg("参数不能为空");
        }
        List<CheckNumVO> list = null;
        try {
            list = endorseService.checkPayPersonNum(listVo);
        } catch (Exception e) {
            e.printStackTrace();
            GenericDataResponse.errorWithMsg("计算人数失败");
        }
        return GenericDataResponse.okWithData(list);
    }

    @ApiOperation(value = "案件关联清单人员列表", httpMethod = "POST")
    @PostMapping(value = "/v1/endorse/getEndorseList", produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
    public ResponseEntity getEndorseList(@RequestBody EndorseListParam param) {
        PageInfo pageInfo = endorseService.getEndorseList(param);
        return GenericListResponse.listAndCount(pageInfo.getList(), pageInfo.getTotal());
    }

    @ApiOperation(value = "案件关联保单时解析清单人员", httpMethod = "GET")
    @GetMapping(value = "/v1/endorse/analysisEndorse", produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
    public ResponseEntity analysisEndorse(@ApiParam(value = "投保单号", required = true) @RequestParam("insuranceId") String insuranceId) {
        return endorseService.analysisEndorse(insuranceId);
    }

    /**
     * 下载批单列表
     */
    @ApiOperation(value = "导出批单列表", notes = "统计结果并下载")
    @GetMapping(value = "/downProEndorseList", produces = {MediaType.APPLICATION_JSON_UTF8_VALUE})
    public void downProEndorseList(EndorsementsEduQueryVO endorsementsEduQueryVO, HttpServletResponse response, HttpServletRequest request) throws Exception {

        //解析结果
        try {
            List list = endorseService.queryProEndorseList(endorsementsEduQueryVO);
            checkStatus(list);
            ExcelUtils.checkNull(list);

            Map<String, List<EduPolicyVO>> beanParams = Maps.newHashMap();
            beanParams.put("items", list);
            //模板位置
            String path = ExcelDownFileEnum.EDU_ENDORSE_DEFAULT.getFilePath();

            Resource resource = new ClassPathResource(path);

            XLSTransformer transformer = new XLSTransformer();
            InputStream inputStream = resource.getInputStream();
            Workbook wb = transformer.transformXLS(inputStream, beanParams);
            String fileName = "批单列表.xls";
            ExcelUtils.compParam(fileName, response, request);
            ServletOutputStream outputStream = response.getOutputStream();
            wb.write(outputStream);
            outputStream.flush();
            inputStream.close();
            outputStream.close();
        } catch (Exception e) {
            log.error("批单列表导出失败!入参:" + JSON.toJSON(endorsementsEduQueryVO), e);
        }

    }


    /**
     * 下载批单列表
     */
    @ApiOperation(value = "导出批单确认列表", notes = "统计结果并下载")
    @GetMapping(value = "/downEndorsementConformList", produces = {MediaType.APPLICATION_JSON_UTF8_VALUE})
    public void downQrProEndorseList(EndorsQueryParam endorsQueryParam, HttpServletResponse response, HttpServletRequest request) throws Exception {
        //解析结果
        try {
            List list = endorseService.endorsementConformList(endorsQueryParam);
            checkStatus(list);
            ExcelUtils.checkNull(list);

            Map<String, List<EduPolicyVO>> beanParams = Maps.newHashMap();
            beanParams.put("items", list);
            //模板位置
            String path = ExcelDownFileEnum.EDU_ACCOUNT_DEFAULT.getFilePath();
            Resource resource = new ClassPathResource(path);
            XLSTransformer transformer = new XLSTransformer();
            InputStream inputStream = resource.getInputStream();
            Workbook wb = transformer.transformXLS(inputStream, beanParams);
            String fileName = "批单确认列表.xls";
            ExcelUtils.compParam(fileName, response, request);
            ServletOutputStream outputStream = response.getOutputStream();
            wb.write(outputStream);
            outputStream.flush();
            inputStream.close();
            outputStream.close();
        } catch (Exception e) {
            log.error("批单列表导出失败!入参:" + JSON.toJSON(endorsQueryParam), e);
        }

    }


    private void checkStatus(List<EduPolicyVO> list) {
        for (EduPolicyVO eduPolicyVO : list) {
            eduPolicyVO.setEndorsementsStatusDesc(EndorsementsStatusEnum.getDescByStatus(eduPolicyVO.getStatus()));
            eduPolicyVO.setEndorsementsTypeDesc(EndorsementsTypeEnum.getDescByType(eduPolicyVO.getEndorsementsType()));
        }
    }

}
